﻿using System;
using System.Configuration;
using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GanagroLiteBO
{
    public class SortableBindingList<T> : BindingList<T>
    {
        #region Fields

        private PropertyDescriptor propertyDescriptor;
        private ListSortDirection listSortDirection;
        private bool isSorted;

        #endregion

        #region Constructors

        /// <summary>
        /// Default constructor
        /// </summary>
        public SortableBindingList()
        {
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="enumerable"></param>
        public SortableBindingList(IEnumerable<T> enumerable)
        {
            if (enumerable == null)
            {
                throw new ArgumentNullException("enumerable");
            }

            foreach (T t in enumerable)
            {
                this.Add(t);
            }
        }

        #endregion

        #region Overriden Methods

        /// <summary>
        /// <see cref="BindingList&lt;T&gt;.SupportsSortingCore"/>
        /// </summary>
        protected override bool SupportsSortingCore
        {
            get { return true; }
        }

        /// <summary>
        /// <see cref="BindingList&lt;T&gt;.IsSortedCore"/>
        /// </summary>
        protected override bool IsSortedCore
        {
            get { return this.isSorted; }
        }

        /// <summary>
        /// <see cref="BindingList&lt;T&gt;.SortPropertyCore"/>
        /// </summary>
        protected override PropertyDescriptor SortPropertyCore
        {
            get { return this.propertyDescriptor; }
        }

        /// <summary>
        /// <see cref="BindingList&lt;T&gt;.SortDirectionCore"/>
        /// </summary>
        protected override ListSortDirection SortDirectionCore
        {
            get { return this.listSortDirection; }
        }

        /// <summary>
        /// <see cref="BindingList&lt;T&gt;.ApplySortCore"/>
        /// </summary>
        protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
        {
            List<T> itemsList = this.Items as List<T>;
            itemsList.Sort(delegate(T t1, T t2)
            {
                this.propertyDescriptor = prop;
                this.listSortDirection = direction;
                this.isSorted = true;

                int reverse = direction == ListSortDirection.Ascending ? 1 : -1;

                object value1 = prop.GetValue(t1);
                object value2 = prop.GetValue(t2);

                return reverse * Comparer.Default.Compare(value1, value2);
            });

            this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }

        /// <summary>
        /// <see cref="BindingList&lt;T&gt;.RemoveSortCore"/>
        /// </summary>
        protected override void RemoveSortCore()
        {
            this.isSorted = false;
            this.propertyDescriptor = base.SortPropertyCore;
            this.listSortDirection = base.SortDirectionCore;
        }

        #endregion
    }
}
